import { spawn } from 'child_process';
import { existsSync, readFileSync, writeFileSync } from 'fs-extra';
import { platform } from 'os';
import path, { join } from 'path';
import { createApp, App } from 'vue';
import Electron from "electron"
import { mkdirSync } from 'fs';
const panelDataMap = new WeakMap<any, App>();
const localPath = join(Editor.Project.path, "profiles/excel2json.json");
/**
 * @zh 如果希望兼容 3.3 之前的版本可以使用下方的代码
 * @en You can add the code below if you want compatibility with versions prior to 3.3
 */
// Editor.Panel.define = Editor.Panel.define || function(options: any) { return options }
module.exports = Editor.Panel.define({
  listeners: {
    show() { console.log('show'); },
    hide() { console.log('hide'); },
  },
  template: readFileSync(join(__dirname, '../../../static/template/default/index.html'), 'utf-8'),
  style: readFileSync(join(__dirname, '../../../static/style/default/index.css'), 'utf-8'),
  $: {
    app: '#app',
    text: '#text',
  },
  methods: {
    hello() {
      if (this.$.text) {
        this.$.text.innerHTML = 'hello';
        console.log('[cocos-panel-html.default]: hello');
      }
    },
  },
  ready() {
    if (this.$.app) {
      const app = createApp({});
      app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('ui-');
      app.component('MyCounter', {
        template: readFileSync(join(__dirname, '../../../static/template/vue/counter.html'), 'utf-8'),
        data() {
          return {
            excelPath: "",
            jsonOutPath: "",
            isPrettier: false,
            tsOutPath: "",
            isExportClientCheckBox: true,
            isExportServerCheckBox: false,

            log: "",
          };
        },
        created() {
          this.readConfig();
          if (!this.jsonOutPath) {
            this.jsonOutPath = path.join(Editor.Project.path, "assets/resources/config");
            this.tsOutPath = path.join(Editor.Project.path, "assets/scripts/config");
          }
        },
        methods: {
          logScrollToBottom() {
            setTimeout(() => {
              const logElement = this.$refs.logTextArea
              logElement.scrollTop = logElement.scrollHeight
            }, 10);
          },
          saveConfig() {
            const data = {
              excelPath: this.excelPath,
              jsonOutPath: this.jsonOutPath,
              isPrettier: this.isPrettier,
              tsOutPath: this.tsOutPath,
              isExportClientCheckBox: this.isExportClientCheckBox,
              isExportServerCheckBox: this.isExportServerCheckBox,
            }
            const dataStr = JSON.stringify(data);
            writeFileSync(localPath, dataStr)
          },

          readConfig() {
            if (existsSync(localPath)) {
              const buf = readFileSync(localPath, 'utf-8')
              const data = JSON.parse(buf.toString())
              if (data) {
                Object.assign(this, data)
              }
            }
          },

          async selectPath(title: string, defaultPath: string) {
            if (!existsSync(defaultPath)) {
              defaultPath = Editor.Project.path
            }
            const res = await Editor.Dialog.select({
              title,
              path: defaultPath,
              type: 'directory'
            })
            return res.filePaths ? res.filePaths[0] : "";
          },

          openPath(path: string) {
            if (existsSync(path)) {
              Electron.shell.showItemInFolder(path)
            } else {
              console.log("打开路径失败", path)
            }
          },

          async onSelectExcelPath() {
            const path = await this.selectPath("选择excel目录", this.excelPath);
            if (path) {
              this.excelPath = path
              this.saveConfig()
            }
          },
          onOpenExcelPath() {
            this.openPath(this.excelPath)
          },

          async onSelectJsonOutPath() {
            const path = await this.selectPath("选择json导出目录", this.jsonOutPath);
            if (path) {
              this.jsonOutPath = path
              this.saveConfig()
            }
          },
          onOpenJsonOutPath() {
            this.openPath(this.jsonOutPath)
          },

          async onSelectTsOutPath() {
            const path = await this.selectPath("选择ts模版导出目录", this.tsOutPath);
            if (path) {
              this.tsOutPath = path
              this.saveConfig()
            }
          },
          onOpenTsOutPath() {
            this.openPath(this.tsOutPath)
          },

          onPrettierCheckBox(e: any) {
            this.isPrettier = e.target.value
            this.saveConfig()
          },

          onExportClientCheckBox(e: any) {
            this.isExportClientCheckBox = e.target.value
            this.saveConfig()
          },

          onExportServerCheckBox(e: any) {
            this.isExportServerCheckBox = e.target.value
            this.saveConfig()
          },

          onGenerate() {
            if(!existsSync(this.tsOutPath)){
              mkdirSync(this.tsOutPath);
            }

            const cmdParams = []
            cmdParams.push(`-excel_in=${this.excelPath}`)
            cmdParams.push(`-json_out=${this.jsonOutPath}`)
            cmdParams.push(`-t=${this.isExportClientCheckBox ? "c" : ""}${this.isExportServerCheckBox ? "s" : ""}`)
            cmdParams.push(`-prettier=${this.isPrettier ? "1" : ""}`)
            cmdParams.push(`-tmpl=${this.tsOutPath}`)
            cmdParams.push(`-exportccc=3.x`)
            //  `-excel_in=${this.excelPath} -json_out=${this.jsonOutPath} -t=cs -prettier=${this.isPrettier ? "1" : ""} -tmpl=${this.tsOutPath}`
            const execuableFileName = platform() == "win32" ? "excel2json.exe" : "excel2json"

            const bin = path.join(__dirname, `../../../bin/${execuableFileName}`)
            const childProcess = spawn(bin, cmdParams, { stdio: 'pipe' })
            this.log = cmdParams.toString() + "\n"
            childProcess.stdout.on(`data`, (data: any) => {
              this.log += data
            });
            childProcess.stderr.on(`data`, (data) => {
              this.log += data
            });
            childProcess.on(`close`, (data) => {
              this.refleshPath(this.jsonOutPath)
              this.refleshPath(this.tsOutPath)
              this.logScrollToBottom();
              // logScrollToBottom()
            });
          },
          cleanLog() {
            this.log = ""
          },
          refleshPath(path: string) {
            const dbPath = `db://assets${path.split("assets")[1]}`
            // Editor.Message.request('asset-db', 'reimport-asset', dbPath);
            Editor.Message.request('asset-db', 'refresh-asset', dbPath);
          }
        },
      });
      app.mount(this.$.app);
      panelDataMap.set(this, app);
    }
  },
  beforeClose() { },
  close() {
    const app = panelDataMap.get(this);
    if (app) {
      app.unmount();
    }
  },
});
